#region COPYRIGHT
//--------------------------------------------------------------------------------
// <copyright file="RandomPixel.cs" company="starLiGHT Entertainment Studios">
//    Copyright (c) 2007, 2008, 2009, 2010, 2011
//       Roland Rosenkranz (Glatzemann@email.de)
//
//    Based on libnoise by Jason Bevins
//      Copyright (C) 2003, 2004 Jason Bevins (licensed under LGPL)
// </copyright>
// <license>
//   This file is part of starLiGHT.Noise.
//
//   starLiGHT.Noise is free software: you can redistribute it and/or modify
//   it under the terms of the GNU Lesser General Public License as published by
//   the Free Software Foundation, either version 3 of the License, or
//   (at your option) any later version.
//
//   starLiGHT.Noise is distributed in the hope that it will be useful,
//   but WITHOUT ANY WARRANTY; without even the implied warranty of
//   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
//   GNU Lesser General Public License for more details.
//
//   You should have received a copy of the GNU Lesser General Public License
//   along with starLiGHT.Noise. If not, see http://www.gnu.org/licenses/.
//    
//   ADDITIONAL (commercial) LICENSES for starLiGHT.Noise are available on request.
// </license>
// <version>
// **************[ starLiGHT.Engine SVN ]**********************
// * $Rev:: 10370                 $:  Revision of last commit *
// * $Author:: unknown            $:  Author of last commit   *
// * $Date:: 2011-06-12 12:29:10 #$:  Date of last commit     *
// ************************************************************
// </version>
//--------------------------------------------------------------------------------
#endregion

namespace starLiGHT.Noise.Noise
{
    #region Using Statements
    using System;
    using System.Collections.Generic;
    using System.Text;

    #endregion

    public class RandomPixel : Module
    {
        /// Default noise this.seed for the noise::module::RandomPixel module.
        private const int DEFAULT_RANDOM_PIXEL_SEED = 0;

        private const int DEFAULT_LEFT = 0;
        private const int DEFAULT_RIGHT = 255;
        private const int DEFAULT_TOP = 0;
        private const int DEFAULT_BOTTOM = 255;

        private const int DEFAULT_PIXEL_COUNT = 128;
        private const int DEFAULT_MAX_PIXEL = 65536;

        private List<Parameter> parameterList;

        private double[,] pixels;

        private int left;
        private int right;
        private int top;
        private int bottom;
        private int pixelCount;
        private int seed;

        private Random rnd;

        /// Constructor.
        public RandomPixel() 
            : base(0)
        {
            this.left = DEFAULT_LEFT;
            this.right = DEFAULT_RIGHT;
            this.top = DEFAULT_TOP;
            this.bottom = DEFAULT_BOTTOM;
            this.seed = DEFAULT_RANDOM_PIXEL_SEED;
            this.pixelCount = DEFAULT_PIXEL_COUNT;
        }

        public override List<Parameter> ParameterList
        {
            get
            {
                if (this.parameterList == null)
                {
                    this.parameterList = new List<Parameter>();
                    this.parameterList.Add(new Parameter("Seed", "int", DEFAULT_RANDOM_PIXEL_SEED, int.MinValue, int.MaxValue));
                    this.parameterList.Add(new Parameter("PixelCount", "int", DEFAULT_PIXEL_COUNT, 1, (255 * 255)));
                }

                return this.parameterList;
            }
        }

        public override double GetValue(double x, double y, double z, double lowerXBound, double upperXBound, double lowerZBound, double upperZBound)
        {
            this.RefreshPixels(lowerXBound, upperXBound, lowerZBound, upperZBound);

            double width = upperXBound - lowerXBound;
            double height = upperZBound - lowerZBound;

            int coordX = (int)Math.Floor(noisegen.MakeInt32Range(((double)(this.right - this.left)) / width * (x - lowerXBound)));
            int coordY = (int)Math.Floor(noisegen.MakeInt32Range(((double)(this.bottom - this.top)) / height * (z - lowerZBound)));

            if (coordX < this.left || coordX >= this.right ||
                coordY < this.top || coordY >= this.bottom)
            {
                return -1.0;
            }
            else
            {
                return this.pixels[coordX, coordY];
            }
        }

        public override void SetParameter(string name, object value)
        {
            switch (name.ToLower())
            {
                case "this.seed":
                    this.seed = Convert.ToInt32(value);
                    this.pixels = null;
                    break;
                case "pixelcount":
                    this.pixelCount = Convert.ToInt32(value);
                    this.pixels = null;
                    break;
            }
        }

        public override object GetParameter(string name)
        {
            switch (name.ToLower())
            {
                case "this.seed": return this.seed;
                case "pixelcount": return this.pixelCount;
            }

            return null;
        }

        private void RefreshPixels(double lowerXBound, double upperXBound, double lowerZBound, double upperZBound)
        {
            if (this.pixels == null)
            {
                this.rnd = new Random(this.seed);

                this.pixels = new double[this.right - this.left, this.bottom - this.top];

                for (int x = 0; x < this.right - this.left; x++)
                {
                    for (int y = 0; y < this.bottom - this.top; y++)
                    {
                        this.pixels[x, y] = -1.0;
                    }
                }

                for (int i = 0; i < this.pixelCount; i++)
                {
                    this.pixels[this.rnd.Next(this.left, this.right), this.rnd.Next(this.top, this.bottom)] = 1.0;
                }
            }
        }
    }    
}

